package cn.shopifymall;

import cn.shopifymall.processor.SocketProcessor;
import cn.shopifymall.utils.Context;
import cn.shopifymall.utils.WebappClassLoader;

import javax.servlet.Servlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author 孤风雪影
 * @Email gitee.com/efairy520
 * @Date 2024/2/26 23:04
 * @Version 1.0
 * 手写Tomcat
 */
public class Tomcat {

    private Map<String, Context> contextMap = new HashMap<>();

    public static void main(String[] args) {
        Tomcat tomcat = new Tomcat();
        tomcat.deployApps();
        tomcat.start();
    }

    public Map<String, Context> getContextMap() {
        return contextMap;
    }

    public void setContextMap(Map<String, Context> contextMap) {
        this.contextMap = contextMap;
    }

    private void deployApps() {
        File webapps = new File(System.getProperty("user.dir"), "\\Tomcat\\webapps");
        for (String app : webapps.list()) {
            deployApp(webapps, app);
        }
    }

    private void deployApp(File webapps, String appName) {
        //有哪些Servlet
        Context context = new Context(appName);

        File appDirectory = new File(webapps, appName);
        File classesDirectory = new File(appDirectory, "classes");
        List<File> files = getAllFiles(classesDirectory);
        for (File file : files) {
            String name = file.getPath();
            name = name.replace(classesDirectory.getPath() + "\\", "");
            name = name.replace(".class", "");
            name = name.replace("\\", ".");


            try {
                WebappClassLoader classLoader = new WebappClassLoader(new URL[]{classesDirectory.toURL()});
                Class<?> servletClass = classLoader.loadClass(name);
                if (HttpServlet.class.isAssignableFrom(servletClass)) {
                    WebServlet annotation = servletClass.getAnnotation(WebServlet.class);
                    String[] urlPatterns = annotation.urlPatterns();

                    for (String urlPattern : urlPatterns) {
                        context.addUrlPatternMapping(urlPattern, (Servlet) servletClass.newInstance());
                    }
                }
            } catch (MalformedURLException e) {
                throw new RuntimeException(e);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }

        }

        contextMap.put(appName, context);
    }

    public List<File> getAllFiles(File folder) {
        List<File> result = new ArrayList<>();
        File[] files = folder.listFiles();

        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    result.addAll(getAllFiles(file));
                } else {
                    result.add(file);
                }
            }
        }
        return result;
    }

    public void start() {
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        try {
            //监听8090端口
            ServerSocket serverSocket = new ServerSocket(8090);
            //不断的获取连接
            while (true) {
                //获取连接，BIO
                Socket socket = serverSocket.accept();
                //异步处理连接
                executorService.execute(new SocketProcessor(socket, this));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
